import { ApiMsgEnum, EntityTypeEnum, IClientInput, IMsgClientSync, InputTypeEnum, IState, toFixed } from "../Common"
import { Connection } from "../Core"
import { Player } from "./Player"
import { PlayerManager } from "./PlayerManager"
import { RoomManager } from "./RoomManager"

export class Room {
    id: number
    players: Set<Player> = new Set()

    lastTime: number
    pendingInput: IClientInput[] = [] // 存储玩家的输入事件
    lastPlayerFrameIdMap: Map<number, number> = new Map() // 存储每个玩家的上一次输入事件的帧 ID

    constructor(rid: number) {
        this.id = rid
    }

    join(uid: number) { // 玩家加入房间
        const player = PlayerManager.Instance.idMapPlayer.get(uid)
        if (player) {
            player.rid = this.id
            this.players.add(player)
        }
    }

    leave(uid: number) { // 玩家离开房间
        const player = PlayerManager.Instance.idMapPlayer.get(uid)
        if (player) {
            player.rid = null
            this.players.delete(player)
            if (!this.players.size) { // 如果房间内没有玩家了，则删除房间
                RoomManager.Instance.closeRoom(this.id)
            }
        }
    }

    close() {
        this.players.clear()
    }

    sync() { // 同步当前房间信息给所有房间内的玩家
        const room = RoomManager.Instance.getRoomView(this)
        for (const player of this.players) {
            player.connection.sendMsg(ApiMsgEnum.MsgRoom, { room })
        }
    }

    start() {
        // 游戏开始时，初始化游戏状态
        const state: IState = {
            actors: [...this.players].map((player, index) => ({
                id: player.id,
                nickname: player.nickname,
                hp: 100,
                type: EntityTypeEnum.Actor1,
                weaponType: EntityTypeEnum.Weapon1,
                bulletType: EntityTypeEnum.Bullet2,
                position: {
                    x: -150 + index * 300,
                    y: -150 + index * 300,
                },
                direction: {
                    x: 1,
                    y: 0,
                },
            })),
            bullets: [],
            nextBulletId: 1,
            seed: 1,
        }

        for (const player of this.players) {
            player.connection.sendMsg(ApiMsgEnum.MsgGameStart, { state })

            // 同时开始监听玩家的输入事件
            player.connection.listenMsg(ApiMsgEnum.MsgClientSync, this.getClientMsg, this)
        }

        const timer1 = setInterval(() => {
            this.sendServerMsg(), 100
        })

        const timer2 = setInterval(() => {
            this.timePast(), 16
        })
    }

    getClientMsg(connection: Connection, { input, frameId }: IMsgClientSync) {
        this.pendingInput.push(input)
        this.lastPlayerFrameIdMap.set(connection.playerId, frameId)
    }

    sendServerMsg() {
        const inputs = this.pendingInput
        this.pendingInput = []
        for (const player of this.players) {
            player.connection.sendMsg(ApiMsgEnum.MsgServerSync, {
                lastFrameId: this.lastPlayerFrameIdMap.get(player.id) ?? 0,
                inputs
            })
        }
    }

    timePast() {
        const now = process.uptime()
        const dt = now - (this.lastTime ?? now)
        this.pendingInput.push({
            type: InputTypeEnum.TimePast,
            dt: toFixed(dt),
        })
        this.lastTime = now
    }
}
